package com.avocado.base.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.Predicate;

import com.avocado.base.dto.role.RoleAddDto;
import com.avocado.base.dto.role.RoleEditDto;
import com.avocado.base.repository.UserRoleRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import com.avocado.base.dto.role.RoleQueryDto;
import com.avocado.base.entity.Role;
import com.avocado.base.repository.ResourcesRoleRepository;
import com.avocado.base.repository.RoleRepository;
import com.avocado.base.service.RoleService;



@Service
public class RoleServiceImpl implements RoleService {
	

	private final RoleRepository roleRepository;
	

	private final ResourcesRoleRepository resourcesRoleRepository;


	private final UserRoleRepository userRoleRepository;

	public RoleServiceImpl(RoleRepository roleRepository, ResourcesRoleRepository resourcesRoleRepository, UserRoleRepository userRoleRepository) {
		this.roleRepository = roleRepository;
		this.resourcesRoleRepository = resourcesRoleRepository;
		this.userRoleRepository = userRoleRepository;
	}

	@Override
	public Role getOne(Long id) {
		

		
		return roleRepository.getOne(id);

	}
	@Override
    public Long add(RoleAddDto t) {

		Role role=new Role();

		BeanUtils.copyProperties(t,role);

		role.setCode(role.getCode().toUpperCase());

    	roleRepository.saveAndFlush(role);

		return role.getId();

	}
    
    
	@Override
    public void update(RoleEditDto t) {
   	 

      	Role old=roleRepository.getOne(t.getId());

		BeanUtils.copyProperties(t,old);

		old.setCode(old.getCode().toUpperCase());

     	roleRepository.saveAndFlush(old);

	}
	@Override
    public  Page<Role> findByPage(Pageable pageable,RoleQueryDto dto) {

      	return  roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {

         List<Predicate> predicates = new ArrayList<>();

         if(!StringUtils.isEmpty(dto.getCode())){
             predicates.add(criteriaBuilder.like(root.get("code").as(String.class),"%".concat(dto.getCode().toUpperCase()).concat("%")));
         }
         
         if(!StringUtils.isEmpty(dto.getName())){
             predicates.add(criteriaBuilder.like(root.get("name").as(String.class),"%".concat(dto.getName().toUpperCase()).concat("%")));
         }

         Predicate[] predicateArray = new Predicate[predicates.size()];

         return criteriaBuilder.and(predicates.toArray(predicateArray));
     }, pageable);

    }
    
	@Override
	public List<Role> findAll(RoleQueryDto dto) {

    	return   roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {

        List<Predicate> predicates = new ArrayList<>();

        if(!StringUtils.isEmpty(dto.getCode())){
            predicates.add(criteriaBuilder.like(root.get("code").as(String.class),"%".concat(dto.getCode().toUpperCase()).concat("%")));
        }
        
        if(!StringUtils.isEmpty(dto.getName())){
            predicates.add(criteriaBuilder.like(root.get("name").as(String.class),"%".concat(dto.getName().toUpperCase()).concat("%")));
        }
        Predicate[] predicateArray = new Predicate[predicates.size()];

        return criteriaBuilder.and(predicates.toArray(predicateArray));
    });


	}
    
    
    
	@Override
	@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor=Exception.class)
    public Boolean deleteById(Long id) {

		Role old=roleRepository.getOne(id);

		if(old.getId() ==1L) {

			return Boolean.FALSE;
		}
		userRoleRepository.deleteAllByRoleId(id);

		resourcesRoleRepository.deleteAllByRoleId(id);
		
		roleRepository.delete(old);
		
		return Boolean.TRUE;
	}
	
  
	@Override
	public List<Role> findAllByCategory(String category) {

		return roleRepository.findAllByCategory(category);

	}
	
	@Override
	public List<Role> findAll() {

		return roleRepository.findAll();
	}
	@Override
   public Role findByCode(String code) {

		List<Role> roleList=roleRepository.findByCode(code);

		return !roleList.isEmpty() ?roleList.get(0):null;

	}

	public List<Role> findAllRoleForUser(Long userId) {

		return userRoleRepository.findAllRoleForUser(userId);
	}


}
